package it.antonio.ilpizze.reflection;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

public class Reflection {
	public static Class<?> getClass(String className) {
		try {
			return Class.forName(className);
		} catch (ClassNotFoundException e) {
			throw new ReflectionException(e.getMessage(), e);
		}
	}

	public static Class<?>[] getClasses(Object...args) {
		Class<?>[] classes = new Class[args.length];
		for(int i = 0; i < classes.length; i++){
			classes[i] = args[i].getClass();
		}
		return classes;
	}

	public static <T> T newInstance(Class<T> clazz) {
		try {
			return clazz.newInstance();
		} catch (InstantiationException e) {
			throw new ReflectionException(e.getMessage(), e);
		} catch (IllegalAccessException e) {
			throw new ReflectionException(e.getMessage(), e);
		}
	}

	public static Object newInstance(String className) {
		return newInstance(getClass(className));
	}

	public static <T> T newInstance(Clazz<T> clazz) {
		return newInstance(clazz.getType());
	}

	public void setProperty(Object instance, String property, Object value) {
		Clazz<?> descr = Clazz.get(instance.getClass());
		String methodName = "set" + property.substring(0, 1).toUpperCase()
				+ property.substring(1, property.length());
		MethodAccessor method = descr.findMethod(methodName,
				new Class<?>[] { value.getClass() });
		method.invoke(instance, value);
	}

	public Class<?> loadFromJar(File jar, String className) {
		URLClassLoader child;
		try {
			child = new URLClassLoader(new URL[] { jar.toURI().toURL() }, this
					.getClass().getClassLoader());
			return Class.forName(className, true, child);
		} catch (MalformedURLException e) {
			throw new ReflectionException(e.getMessage(), e);
		} catch (ClassNotFoundException e) {
			throw new ReflectionException(e.getMessage(), e);
		}
	}

	public static void invokeMethod(Object instance, String eventMethod) {
		Class<?> clazz = instance.getClass();
		Clazz<?> descr = Clazz.get(clazz);
		MethodAccessor method = descr.findMethod(eventMethod, new Class[] {});
		if (method != null) {
			method.invoke(instance, new Object[] {});
		} else {
			throw new ReflectionException("method " + eventMethod
					+ " doesn't exist");
		}
	}


}